home *** CD-ROM | disk | FTP | other *** search
/ Languguage OS 2 / Languguage OS II Version 10-94 (Knowledge Media)(1994).ISO / a_utils / flex / amiga / flex.lha / Flex.src.lha / misc.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-03-13  |  14.7 KB  |  834 lines

  1. /* misc - miscellaneous flex routines */
  2.  
  3. /*-
  4.  * Copyright (c) 1990 The Regents of the University of California.
  5.  * All rights reserved.
  6.  *
  7.  * This code is derived from software contributed to Berkeley by
  8.  * Vern Paxson.
  9.  * 
  10.  * The United States Government has rights in this work pursuant
  11.  * to contract no. DE-AC03-76SF00098 between the United States
  12.  * Department of Energy and the University of California.
  13.  *
  14.  * Redistribution and use in source and binary forms are permitted provided
  15.  * that: (1) source distributions retain this entire copyright notice and
  16.  * comment, and (2) distributions including binaries display the following
  17.  * acknowledgement:  ``This product includes software developed by the
  18.  * University of California, Berkeley and its contributors'' in the
  19.  * documentation or other materials provided with the distribution and in
  20.  * all advertising materials mentioning features or use of this software.
  21.  * Neither the name of the University nor the names of its contributors may
  22.  * be used to endorse or promote products derived from this software without
  23.  * specific prior written permission.
  24.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
  25.  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  26.  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  27.  */
  28.  
  29. #ifndef lint
  30. static char rcsid[] =
  31.     "@(#) $Header: /usr/fsys/odin/a/vern/flex/RCS/misc.c,v 2.9 90/08/14 00:10:24 vern Exp $ (LBL)";
  32. #endif
  33.  
  34. #include <ctype.h>
  35. #include "flexdef.h"
  36.  
  37. #ifdef AMIGA
  38. #include "misc.i" /* Include the prototypes */
  39. #endif
  40.  
  41. /* ANSI C does not guarantee that isascii() is defined */
  42. #ifndef isascii
  43. #define isascii(c) ((c) <= 0177)
  44. #endif
  45.  
  46.  
  47.  
  48. /* declare functions that have forward references */
  49.  
  50. void dataflush PROTO(());
  51. int otoi PROTO((Char []));
  52.  
  53.  
  54. /* action_out - write the actions from the temporary file to lex.yy.c
  55.  *
  56.  * synopsis
  57.  *     action_out();
  58.  *
  59.  *     Copies the action file up to %% (or end-of-file) to lex.yy.c
  60.  */
  61.  
  62. void action_out()
  63.  
  64.     {
  65.     char buf[MAXLINE];
  66.  
  67.     while ( fgets( buf, MAXLINE, temp_action_file ) != NULL )
  68.     if ( buf[0] == '%' && buf[1] == '%' )
  69.         break;
  70.     else
  71.         fputs( buf, stdout );
  72.     }
  73.  
  74.  
  75. /* allocate_array - allocate memory for an integer array of the given size */
  76.  
  77. void *allocate_array( size, element_size )
  78. int size, element_size;
  79.  
  80.     {
  81.     register void *mem;
  82.  
  83.     /* on 16-bit int machines (e.g., 80286) we might be trying to
  84.      * allocate more than a signed int can hold, and that won't
  85.      * work.  Cheap test:
  86.      */
  87.     if ( element_size * size <= 0 )
  88.         flexfatal( "request for < 1 byte in allocate_array()" );
  89.  
  90.     mem = (void *) malloc( (unsigned) (element_size * size) );
  91.  
  92.     if ( mem == NULL )
  93.     flexfatal( "memory allocation failed in allocate_array()" );
  94.  
  95.     return ( mem );
  96.     }
  97.  
  98.  
  99. /* all_lower - true if a string is all lower-case
  100.  *
  101.  * synopsis:
  102.  *    Char *str;
  103.  *    int all_lower();
  104.  *    true/false = all_lower( str );
  105.  */
  106.  
  107. int all_lower( str )
  108. register Char *str;
  109.  
  110.     {
  111.     while ( *str )
  112.     {
  113.     if ( ! isascii( *str ) || ! islower( *str ) )
  114.         return ( 0 );
  115.     ++str;
  116.     }
  117.  
  118.     return ( 1 );
  119.     }
  120.  
  121.  
  122. /* all_upper - true if a string is all upper-case
  123.  *
  124.  * synopsis:
  125.  *    Char *str;
  126.  *    int all_upper();
  127.  *    true/false = all_upper( str );
  128.  */
  129.  
  130. int all_upper( str )
  131. register Char *str;
  132.  
  133.     {
  134.     while ( *str )
  135.     {
  136.     if ( ! isascii( *str ) || ! isupper( (char) *str ) )
  137.         return ( 0 );
  138.     ++str;
  139.     }
  140.  
  141.     return ( 1 );
  142.     }
  143.  
  144.  
  145. /* bubble - bubble sort an integer array in increasing order
  146.  *
  147.  * synopsis
  148.  *   int v[n], n;
  149.  *   bubble( v, n );
  150.  *
  151.  * description
  152.  *   sorts the first n elements of array v and replaces them in
  153.  *   increasing order.
  154.  *
  155.  * passed
  156.  *   v - the array to be sorted
  157.  *   n - the number of elements of 'v' to be sorted */
  158.  
  159. void bubble( v, n )
  160. int v[], n;
  161.  
  162.     {
  163.     register int i, j, k;
  164.  
  165.     for ( i = n; i > 1; --i )
  166.     for ( j = 1; j < i; ++j )
  167.         if ( v[j] > v[j + 1] )    /* compare */
  168.         {
  169.         k = v[j];    /* exchange */
  170.         v[j] = v[j + 1];
  171.         v[j + 1] = k;
  172.         }
  173.     }
  174.  
  175.  
  176. /* clower - replace upper-case letter to lower-case
  177.  *
  178.  * synopsis:
  179.  *    Char clower();
  180.  *    int c;
  181.  *    c = clower( c );
  182.  */
  183.  
  184. Char clower( c )
  185. register int c;
  186.  
  187.     {
  188.     return ((Char)( (isascii( c ) && isupper( c )) ? tolower( c ) : c ));
  189.     }
  190.  
  191.  
  192. /* copy_string - returns a dynamically allocated copy of a string
  193.  *
  194.  * synopsis
  195.  *    char *str, *copy, *copy_string();
  196.  *    copy = copy_string( str );
  197.  */
  198.  
  199. char *copy_string( str )
  200. register char *str;
  201.  
  202.     {
  203.     register char *c;
  204.     char *copy;
  205.  
  206.     /* find length */
  207.     for ( c = str; *c; ++c )
  208.     ;
  209.  
  210.     copy = malloc( (unsigned) ((c - str + 1) * sizeof( char )) );
  211.  
  212.     if ( copy == NULL )
  213.     flexfatal( "dynamic memory failure in copy_string()" );
  214.  
  215.     for ( c = copy; (*c++ = *str++); )
  216.     ;
  217.  
  218.     return ( copy );
  219.     }
  220.  
  221.  
  222. /* copy_unsigned_string -
  223.  *    returns a dynamically allocated copy of a (potentially) unsigned string
  224.  *
  225.  * synopsis
  226.  *    Char *str, *copy, *copy_unsigned_string();
  227.  *    copy = copy_unsigned_string( str );
  228.  */
  229.  
  230. Char *copy_unsigned_string( str )
  231. register Char *str;
  232.  
  233.     {
  234.     register Char *c;
  235.     Char *copy;
  236.  
  237.     /* find length */
  238.     for ( c = str; *c; ++c )
  239.     ;
  240.  
  241.     copy = (Char *) malloc( (unsigned) ((c - str + 1) * sizeof( Char )) );
  242.  
  243.     if ( copy == NULL )
  244.     flexfatal( "dynamic memory failure in copy_unsigned_string()" );
  245.  
  246.     for ( c = copy; (*c++ = *str++); )
  247.     ;
  248.  
  249.     return ( copy );
  250.     }
  251.  
  252.  
  253. /* cshell - shell sort a character array in increasing order
  254.  *
  255.  * synopsis
  256.  *
  257.  *   Char v[n];
  258.  *   int n, special_case_0;
  259.  *   cshell( v, n, special_case_0 );
  260.  *
  261.  * description
  262.  *   does a shell sort of the first n elements of array v.
  263.  *   If special_case_0 is true, then any element equal to 0
  264.  *   is instead assumed to have infinite weight.
  265.  *
  266.  * passed
  267.  *   v - array to be sorted
  268.  *   n - number of elements of v to be sorted
  269.  */
  270.  
  271. void cshell( v, n, special_case_0 )
  272. Char v[];
  273. int n, special_case_0;
  274.  
  275.     {
  276.     int gap, i, j, jg;
  277.     Char k;
  278.  
  279.     for ( gap = n / 2; gap > 0; gap = gap / 2 )
  280.     for ( i = gap; i < n; ++i )
  281.         for ( j = i - gap; j >= 0; j = j - gap )
  282.         {
  283.         jg = j + gap;
  284.  
  285.         if ( special_case_0 )
  286.             {
  287.             if ( v[jg] == 0 )
  288.             break;
  289.  
  290.             else if ( v[j] != 0 && v[j] <= v[jg] )
  291.             break;
  292.             }
  293.  
  294.         else if ( v[j] <= v[jg] )
  295.             break;
  296.  
  297.         k = v[j];
  298.         v[j] = v[jg];
  299.         v[jg] = k;
  300.         }
  301.     }
  302.  
  303.  
  304. /* dataend - finish up a block of data declarations
  305.  *
  306.  * synopsis
  307.  *    dataend();
  308.  */
  309.  
  310. void dataend()
  311.  
  312.     {
  313.     if ( datapos > 0 )
  314.     dataflush();
  315.  
  316.     /* add terminator for initialization */
  317.     puts( "    } ;\n" );
  318.  
  319.     dataline = 0;
  320.     datapos = 0;
  321.     }
  322.  
  323.  
  324.  
  325. /* dataflush - flush generated data statements
  326.  *
  327.  * synopsis
  328.  *    dataflush();
  329.  */
  330.  
  331. void dataflush()
  332.  
  333.     {
  334.     putchar( '\n' );
  335.  
  336.     if ( ++dataline >= NUMDATALINES )
  337.     {
  338.     /* put out a blank line so that the table is grouped into
  339.      * large blocks that enable the user to find elements easily
  340.      */
  341.     putchar( '\n' );
  342.     dataline = 0;
  343.     }
  344.  
  345.     /* reset the number of characters written on the current line */
  346.     datapos = 0;
  347.     }
  348.  
  349.  
  350. /* flexerror - report an error message and terminate
  351.  *
  352.  * synopsis
  353.  *    char msg[];
  354.  *    flexerror( msg );
  355.  */
  356.  
  357. void flexerror( msg )
  358. char msg[];
  359.  
  360.     {
  361.     fprintf( stderr, "%s: %s\n", program_name, msg );
  362.  
  363.     flexend( 1 );
  364.     }
  365.  
  366.  
  367. /* flexfatal - report a fatal error message and terminate
  368.  *
  369.  * synopsis
  370.  *    char msg[];
  371.  *    flexfatal( msg );
  372.  */
  373.  
  374. void flexfatal( msg )
  375. char msg[];
  376.  
  377.     {
  378.     fprintf( stderr, "%s: fatal internal error, %s\n", program_name, msg );
  379.     flexend( 1 );
  380.     }
  381.  
  382.  
  383. /* flex_gettime - return current time
  384.  *
  385.  * synopsis
  386.  *    char *flex_gettime(), *time_str;
  387.  *    time_str = flex_gettime();
  388.  *
  389.  * note
  390.  *    the routine name has the "flex_" prefix because of name clashes
  391.  *    with Turbo-C
  392.  */
  393.  
  394. /* include sys/types.h to use time_t and make lint happy */
  395.  
  396. #ifndef MS_DOS
  397. #ifndef VMS
  398. #include <sys/types.h>
  399. #else
  400. #include <types.h>
  401. #endif
  402. #endif
  403.  
  404. #ifdef MS_DOS
  405. #include <time.h>
  406. typedef long time_t;
  407. #endif
  408.  
  409. #ifdef AMIGA
  410. #include <time.h>
  411. #endif
  412.  
  413. char *flex_gettime()
  414.  
  415.     {
  416.     time_t t, time();
  417.     char *result, *ctime(), *copy_string();
  418.  
  419.     t = time( (long *) 0 );
  420.  
  421.     result = copy_string( ctime( &t ) );
  422.  
  423.     /* get rid of trailing newline */
  424.     result[24] = '\0';
  425.  
  426.     return ( result );
  427.     }
  428.  
  429.  
  430. /* lerrif - report an error message formatted with one integer argument
  431.  *
  432.  * synopsis
  433.  *    char msg[];
  434.  *    int arg;
  435.  *    lerrif( msg, arg );
  436.  */
  437.  
  438. void lerrif( msg, arg )
  439. char msg[];
  440. int arg;
  441.  
  442.     {
  443.     char errmsg[MAXLINE];
  444.     (void) sprintf( errmsg, msg, arg );
  445.     flexerror( errmsg );
  446.     }
  447.  
  448.  
  449. /* lerrsf - report an error message formatted with one string argument
  450.  *
  451.  * synopsis
  452.  *    char msg[], arg[];
  453.  *    lerrsf( msg, arg );
  454.  */
  455.  
  456. void lerrsf( msg, arg )
  457. char msg[], arg[];
  458.  
  459.     {
  460.     char errmsg[MAXLINE];
  461.  
  462.     (void) sprintf( errmsg, msg, arg );
  463.     flexerror( errmsg );
  464.     }
  465.  
  466.  
  467. /* htoi - convert a hexadecimal digit string to an integer value
  468.  *
  469.  * synopsis:
  470.  *    int val, htoi();
  471.  *    Char str[];
  472.  *    val = htoi( str );
  473.  */
  474.  
  475. int htoi( str )
  476. Char str[];
  477.  
  478.     {
  479.     int result;
  480.  
  481.     (void) sscanf( (char *) str, "%x", &result );
  482.  
  483.     return ( result );
  484.     }
  485.  
  486.  
  487. /* is_hex_digit - returns true if a character is a valid hex digit, false
  488.  *          otherwise
  489.  *
  490.  * synopsis:
  491.  *    int true_or_false, is_hex_digit();
  492.  *    int ch;
  493.  *    val = is_hex_digit( ch );
  494.  */
  495.  
  496. int is_hex_digit( ch )
  497. int ch;
  498.  
  499.     {
  500.     if ( isdigit( ch ) )
  501.     return ( 1 );
  502.  
  503.     switch ( clower( ch ) )
  504.     {
  505.     case 'a':
  506.     case 'b':
  507.     case 'c':
  508.     case 'd':
  509.     case 'e':
  510.     case 'f':
  511.         return ( 1 );
  512.  
  513.     default:
  514.         return ( 0 );
  515.     }
  516.     }
  517.  
  518.  
  519. /* line_directive_out - spit out a "# line" statement */
  520.  
  521. void line_directive_out( output_file_name )
  522. FILE *output_file_name;
  523.  
  524.     {
  525.     if ( infilename && gen_line_dirs )
  526.         fprintf( output_file_name, "# line %d \"%s\"\n", linenum, infilename );
  527.     }
  528.  
  529.  
  530. /* mk2data - generate a data statement for a two-dimensional array
  531.  *
  532.  * synopsis
  533.  *    int value;
  534.  *    mk2data( value );
  535.  *
  536.  *  generates a data statement initializing the current 2-D array to "value"
  537.  */
  538. void mk2data( value )
  539. int value;
  540.  
  541.     {
  542.     if ( datapos >= NUMDATAITEMS )
  543.     {
  544.     putchar( ',' );
  545.     dataflush();
  546.     }
  547.  
  548.     if ( datapos == 0 )
  549.     /* indent */
  550.     fputs( "    ", stdout );
  551.  
  552.     else
  553.     putchar( ',' );
  554.  
  555.     ++datapos;
  556.  
  557.     printf( "%5d", value );
  558.     }
  559.  
  560.  
  561. /* mkdata - generate a data statement
  562.  *
  563.  * synopsis
  564.  *    int value;
  565.  *    mkdata( value );
  566.  *
  567.  *  generates a data statement initializing the current array element to
  568.  *  "value"
  569.  */
  570. void mkdata( value )
  571. int value;
  572.  
  573.     {
  574.     if ( datapos >= NUMDATAITEMS )
  575.     {
  576.     putchar( ',' );
  577.     dataflush();
  578.     }
  579.  
  580.     if ( datapos == 0 )
  581.     /* indent */
  582.     fputs( "    ", stdout );
  583.  
  584.     else
  585.     putchar( ',' );
  586.  
  587.     ++datapos;
  588.  
  589.     printf( "%5d", value );
  590.     }
  591.  
  592.  
  593. /* myctoi - return the integer represented by a string of digits
  594.  *
  595.  * synopsis
  596.  *    Char array[];
  597.  *    int val, myctoi();
  598.  *    val = myctoi( array );
  599.  *
  600.  */
  601.  
  602. int myctoi( array )
  603. Char array[];
  604.  
  605.     {
  606.     int val = 0;
  607.  
  608.     (void) sscanf( (char *) array, "%d", &val );
  609.  
  610.     return ( val );
  611.     }
  612.  
  613.  
  614. /* myesc - return character corresponding to escape sequence
  615.  *
  616.  * synopsis
  617.  *    Char array[], c, myesc();
  618.  *    c = myesc( array );
  619.  *
  620.  */
  621.  
  622. Char myesc( array )
  623. Char array[];
  624.  
  625.     {
  626.     Char c, esc_char;
  627.     register int sptr;
  628.  
  629.     switch ( array[1] )
  630.     {
  631.     case 'a': return ( '\a' );
  632.     case 'b': return ( '\b' );
  633.     case 'f': return ( '\f' );
  634.     case 'n': return ( '\n' );
  635.     case 'r': return ( '\r' );
  636.     case 't': return ( '\t' );
  637.     case 'v': return ( '\v' );
  638.  
  639.     case '0':
  640.     case '1':
  641.     case '2':
  642.     case '3':
  643.     case '4':
  644.     case '5':
  645.     case '6':
  646.     case '7':
  647.     case '8':
  648.     case '9':
  649.         { /* \<octal> */
  650.         sptr = 1;
  651.  
  652.         while ( isascii( array[sptr] ) && isdigit( array[sptr] ) )
  653.         /* don't increment inside loop control because if
  654.          * isdigit() is a macro it might expand into multiple
  655.          * increments ...
  656.          */
  657.         ++sptr;
  658.  
  659.         c = array[sptr];
  660.         array[sptr] = '\0';
  661.  
  662.         esc_char = otoi( array + 1 );
  663.  
  664.         array[sptr] = c;
  665.  
  666.         return ( esc_char );
  667.         }
  668.  
  669.     case 'x':
  670.         { /* \x<hex> */
  671.         int sptr = 2;
  672.  
  673.         while ( isascii( array[sptr] ) && is_hex_digit( array[sptr] ) )
  674.         /* don't increment inside loop control because if
  675.          * isdigit() is a macro it might expand into multiple
  676.          * increments ...
  677.          */
  678.         ++sptr;
  679.  
  680.         c = array[sptr];
  681.         array[sptr] = '\0';
  682.  
  683.         esc_char = htoi( array + 2 );
  684.  
  685.         array[sptr] = c;
  686.  
  687.         return ( esc_char );
  688.         }
  689.  
  690.     default:
  691.         return ( array[1] );
  692.     }
  693.     }
  694.  
  695.  
  696. /* otoi - convert an octal digit string to an integer value
  697.  *
  698.  * synopsis:
  699.  *    int val, otoi();
  700.  *    Char str[];
  701.  *    val = otoi( str );
  702.  */
  703.  
  704. int otoi( str )
  705. Char str[];
  706.  
  707.     {
  708.     int result;
  709.  
  710.     (void) sscanf( (char *) str, "%o", &result );
  711.  
  712.     return ( result );
  713.     }
  714.  
  715.  
  716. /* readable_form - return the the human-readable form of a character
  717.  *
  718.  * synopsis:
  719.  *    int c;
  720.  *    char *readable_form();
  721.  *    <string> = readable_form( c );
  722.  *
  723.  * The returned string is in static storage.
  724.  */
  725.  
  726. char *readable_form( c )
  727. register int c;
  728.  
  729.     {
  730.     static char rform[10];
  731.  
  732.     if ( (c >= 0 && c < 32) || c >= 127 )
  733.     {
  734.     switch ( c )
  735.         {
  736.         case '\n': return ( "\\n" );
  737.         case '\t': return ( "\\t" );
  738.         case '\f': return ( "\\f" );
  739.         case '\r': return ( "\\r" );
  740.         case '\b': return ( "\\b" );
  741.  
  742.         default:
  743.         (void) sprintf( rform, "\\%.3o", c );
  744.         return ( rform );
  745.         }
  746.     }
  747.  
  748.     else if ( c == ' ' )
  749.     return ( "' '" );
  750.  
  751.     else
  752.     {
  753.     rform[0] = c;
  754.     rform[1] = '\0';
  755.  
  756.     return ( rform );
  757.     }
  758.     }
  759.  
  760.  
  761. /* reallocate_array - increase the size of a dynamic array */
  762.  
  763. void *reallocate_array( array, size, element_size )
  764. void *array;
  765. int size, element_size;
  766.  
  767.     {
  768.     register void *new_array;
  769.  
  770.     /* same worry as in allocate_array(): */
  771.     if ( size * element_size <= 0 )
  772.         flexfatal( "attempt to increase array size by less than 1 byte" );
  773.  
  774.     new_array =
  775.     (void *) realloc( (char *)array, (unsigned) (size * element_size ));
  776.  
  777.     if ( new_array == NULL )
  778.     flexfatal( "attempt to increase array size failed" );
  779.  
  780.     return ( new_array );
  781.     }
  782.  
  783.  
  784. /* skelout - write out one section of the skeleton file
  785.  *
  786.  * synopsis
  787.  *    skelout();
  788.  *
  789.  * DESCRIPTION
  790.  *    Copies from skelfile to stdout until a line beginning with "%%" or
  791.  *    EOF is found.
  792.  */
  793. void skelout()
  794.  
  795.     {
  796.     char buf[MAXLINE];
  797.  
  798.     while ( fgets( buf, MAXLINE, skelfile ) != NULL )
  799.     if ( buf[0] == '%' && buf[1] == '%' )
  800.         break;
  801.     else
  802.         fputs( buf, stdout );
  803.     }
  804.  
  805.  
  806. /* transition_struct_out - output a yy_trans_info structure
  807.  *
  808.  * synopsis
  809.  *     int element_v, element_n;
  810.  *     transition_struct_out( element_v, element_n );
  811.  *
  812.  * outputs the yy_trans_info structure with the two elements, element_v and
  813.  * element_n.  Formats the output with spaces and carriage returns.
  814.  */
  815.  
  816. void transition_struct_out( element_v, element_n )
  817. int element_v, element_n;
  818.  
  819.     {
  820.     printf( "%7d, %5d,", element_v, element_n );
  821.  
  822.     datapos += TRANS_STRUCT_PRINT_LENGTH;
  823.  
  824.     if ( datapos >= 75 )
  825.     {
  826.     putchar( '\n' );
  827.  
  828.     if ( ++dataline % 10 == 0 )
  829.         putchar( '\n' );
  830.  
  831.     datapos = 0;
  832.     }
  833.     }
  834.